const shader = require('../shader/index');

module.exports = class TileTextureLayer {
    constructor(option) {
        this.id = option.id;
        this.gl = option.gl;
        const gl = option.gl;
        this.globe = option.globe;
        this.radius = option.radius;
        this.textureUrl = option.textureUrl;
        this.isTileRender = option.isTileRender;

        this.seqArr = [];
        this.tilesCach = {};

        // init shader
        const program = gl.createProgram();
        this.program = program;
        const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
        gl.shaderSource(fragmentShader, shader.tileImage.fragmentSource);
        gl.compileShader(fragmentShader);
        gl.attachShader(program, fragmentShader);
        const vertexShader = gl.createShader(gl.VERTEX_SHADER);
        gl.shaderSource(vertexShader, shader.tileImage.vertexSource);
        gl.compileShader(vertexShader);
        gl.attachShader(program, vertexShader);
        gl.linkProgram(program);

        // get attribLocation
        this.attribLocation = {
            a_Position: gl.getAttribLocation(program, 'a_Position'),
            a_TexCoord: gl.getAttribLocation(program, 'a_TexCoord'),
            a_Normal: gl.getAttribLocation(program, 'a_Normal')
        }

        // get uniformLocation
        this.uniformLocation = {
            u_ModelMatrix: gl.getUniformLocation(program, 'u_ModelMatrix'),
            u_ViewMatrix: gl.getUniformLocation(program, 'u_ViewMatrix'),
            u_ProjMatrix: gl.getUniformLocation(program, 'u_ProjMatrix'),
            u_NormalMatrix: gl.getUniformLocation(program, 'u_NormalMatrix'),
            u_LightColor: gl.getUniformLocation(program, 'u_LightColor'),
            u_LightPosition: gl.getUniformLocation(program, 'u_LightPosition'),
            u_AmbientColor: gl.getUniformLocation(program, 'u_AmbientColor'),
            u_Sampler: gl.getUniformLocation(program, 'u_Sampler')
        }

        if (!this.isTileRender) {
            this.getZoomedTileBuffer(2, this.radius)
        }
    }

    getTilesSeq() {
        const distance = this.globe.getZoom();
        let zoomInt = parseInt(this.globe.zoom);
        if (zoomInt < 2) zoomInt = 2;
        const LngLat = this.globe.getLngLat();
        // let zoomInt = 0;
        let leftTile = 0;
        let rightTile = 0;
        let topTile = 0;
        let bottomTile = 0;

        if (zoomInt <= 2) {
            leftTile = 3;
            rightTile = 3;
            topTile = 3;
            bottomTile = 3;
        }
        else if (zoomInt === 3) {
            zoomInt = 3;
            leftTile = 1;
            rightTile = 1;
            topTile = 1;
            bottomTile = 1;
        }
        else if (zoomInt === 4) {
            leftTile = 2;
            rightTile = 2;
            topTile = 2;
            bottomTile = 2;
        }
        else {
            leftTile = 4;
            rightTile = 4;
            topTile = 2;
            bottomTile = 2;
        }
        // 控制缩放逻辑
        // zoomInt = -1.044ln(distance) + 4.7423
        // zoomInt = -1.044 * Math.log(distance) + 4.7423
        // if (distance < 0.03) {
        //     zoomInt = 8;
        //     leftTile = 4;
        //     rightTile = 4;
        //     topTile = 2;
        //     bottomTile = 2;
        // }
        // else if (distance < 0.138) {
        //     zoomInt = 7;
        //     leftTile = 4;
        //     rightTile = 4;
        //     topTile = 2;
        //     bottomTile = 2;
        // }
        // else if (distance < 0.389) {
        //     zoomInt = 6;
        //     leftTile = 4;
        //     rightTile = 4;
        //     topTile = 2;
        //     bottomTile = 2;
        // }
        // else if (distance < 1.008) {
        //     zoomInt = 5;
        //     leftTile = 4;
        //     rightTile = 4;
        //     topTile = 2;
        //     bottomTile = 2;
        // }
        // else if (distance < 2.192) {
        //     zoomInt = 4;
        //     leftTile = 2;
        //     rightTile = 2;
        //     topTile = 2;
        //     bottomTile = 2;
        // }
        // else if (distance < 4.758) {
        //     zoomInt = 3;
        //     leftTile = 1;
        //     rightTile = 1;
        //     topTile = 1;
        //     bottomTile = 1;
        // }
        // else if (distance < 10.5) {
        //     zoomInt = 2;
        //     leftTile = 3;
        //     rightTile = 3;
        //     topTile = 3;
        //     bottomTile = 3;
        // }

        const mercator = lonLat2WebMercator(LngLat[0], LngLat[1]);
        const unit = 20037508.3427892 * 2 / Math.pow(2, zoomInt);
        const cenSeqX = parseInt((mercator[0] + 20037508.3427892) / unit);
        const cenSeqY = parseInt((mercator[1] + 20037508.3427892) / unit);

        let leftSeqX = cenSeqX - leftTile;
        let rightSeqX = cenSeqX + rightTile;
        let bottomSeqX = cenSeqY - bottomTile;
        let topSeqX = cenSeqY + topTile;

        if (leftSeqX < 0) leftSeqX = 0;
        if (rightSeqX > (Math.pow(2, zoomInt) - 1)) rightSeqX = Math.pow(2, zoomInt) - 1;
        if (bottomSeqX < 0) bottomSeqX = 0;
        if (topSeqX > (Math.pow(2, zoomInt) - 1)) topSeqX = Math.pow(2, zoomInt) - 1;

        this.seqArr.splice(0, this.seqArr.length);
        for (let i = leftSeqX; i <= rightSeqX; i++) {
            for (let j = bottomSeqX; j <= topSeqX; j++) {
                if (!this.tilesCach[zoomInt + '+' + i + '+' + j]) {
                    this.tilesCach[zoomInt + '+' + i + '+' + j] = loadTexture(this.radius, this.globe, zoomInt, i, j, this.textureUrl);
                }
                this.seqArr.push(zoomInt + '+' + i + '+' + j);
            }
        }
    }

    getZoomedTileBuffer(n, radius) {
        // 加载墨卡托瓦块
        const tilesCorners = getTilesCorners(n);
        for (let i in tilesCorners) {
            this.seqArr.push(i);
            this.tilesCach[i] = loadTexture(this.radius, this.globe, n, tilesCorners[i].i, tilesCorners[i].j, this.textureUrl);
        }
        // 加载两极（85度以上地区）纹理数据
        const poleTilesCorners = getPoleTilesCorners(n);
        for (let i in poleTilesCorners) {
            this.seqArr.push(i);
            this.tilesCach[i] = loadTexture(this.radius, this.globe, n, poleTilesCorners[i].i, poleTilesCorners[i].j, this.textureUrl, poleTilesCorners[i].pole, poleTilesCorners[i].lbLngLat, poleTilesCorners[i].rtLngLat);
        }
    }

    render(config) {
        const modelMatrix = config.modelMatrix;
        const viewMatrix = config.viewMatrix;
        const projMatrix = config.projMatrix;
        const normalMatrix = config.normalMatrix;

        if (this.isTileRender) {
            this.getTilesSeq();
        }

        const gl = this.gl;
        gl.useProgram(this.program);

        gl.uniform3f(this.uniformLocation.u_AmbientColor, 0.2, 0.2, 0.2);
        gl.uniform3f(this.uniformLocation.u_LightColor, 1.0, 1.0, 1.0);
        gl.uniform3f(this.uniformLocation.u_LightPosition, 0.0, 0.0, 20.0);

        gl.uniformMatrix4fv(this.uniformLocation.u_ModelMatrix, false, modelMatrix);
        gl.uniformMatrix4fv(this.uniformLocation.u_ViewMatrix, false, viewMatrix);
        gl.uniformMatrix4fv(this.uniformLocation.u_ProjMatrix, false, projMatrix);
        gl.uniformMatrix4fv(this.uniformLocation.u_NormalMatrix, false, normalMatrix);

        gl.uniform1i(this.u_Sampler, 0);

        for (let i = 0; i < this.seqArr.length; i++) {
            const tilesBuffer = this.tilesCach[this.seqArr[i]];
            const backwardIndex = (tilesBuffer.zoomInt - 1) + '+' + parseInt(tilesBuffer.x / 2) + '+' + parseInt(tilesBuffer.y / 2);
            const forwardIndex = [
                (tilesBuffer.zoomInt + 1) + '+' + tilesBuffer.x * 2 + '+' + tilesBuffer.y * 2,
                (tilesBuffer.zoomInt + 1) + '+' + (tilesBuffer.x * 2 + 1) + '+' + tilesBuffer.y * 2,
                (tilesBuffer.zoomInt + 1) + '+' + tilesBuffer.x * 2 + '+' + (tilesBuffer.y * 2 + 1),
                (tilesBuffer.zoomInt + 1) + '+' + (tilesBuffer.x * 2 + 1) + '+' + (tilesBuffer.y * 2 + 1)
            ];
            if (tilesBuffer.tileTexture.hasLoad) {
                this.renderTile(tilesBuffer.positionVertexBuffer, tilesBuffer.texCoordVertexBuffer, tilesBuffer.normalVertexBuffer, tilesBuffer.indexBuffer, tilesBuffer.n, tilesBuffer.tileTexture);
            }
            else if (this.tilesCach[backwardIndex] && this.tilesCach[backwardIndex].tileTexture.hasLoad) {
                const tileBuffer = this.tilesCach[backwardIndex];
                this.renderTile(tileBuffer.positionVertexBuffer, tileBuffer.texCoordVertexBuffer, tileBuffer.normalVertexBuffer, tileBuffer.indexBuffer, tileBuffer.n, tileBuffer.tileTexture);
            }
            else {
                if (this.tilesCach[forwardIndex[0]] && this.tilesCach[forwardIndex[0]].tileTexture.hasLoad) {
                    const tileBuffer = this.tilesCach[forwardIndex[0]];
                    this.renderTile(tileBuffer.positionVertexBuffer, tileBuffer.texCoordVertexBuffer, tileBuffer.normalVertexBuffer, tileBuffer.indexBuffer, tileBuffer.n, tileBuffer.tileTexture);
                }
                if (this.tilesCach[forwardIndex[1]] && this.tilesCach[forwardIndex[1]].tileTexture.hasLoad) {
                    const tileBuffer = this.tilesCach[forwardIndex[1]];
                    this.renderTile(tileBuffer.positionVertexBuffer, tileBuffer.texCoordVertexBuffer, tileBuffer.normalVertexBuffer, tileBuffer.indexBuffer, tileBuffer.n, tileBuffer.tileTexture);
                }
                if (this.tilesCach[forwardIndex[2]] && this.tilesCach[forwardIndex[2]].tileTexture.hasLoad) {
                    const tileBuffer = this.tilesCach[forwardIndex[2]];
                    this.renderTile(tileBuffer.positionVertexBuffer, tileBuffer.texCoordVertexBuffer, tileBuffer.normalVertexBuffer, tileBuffer.indexBuffer, tileBuffer.n, tileBuffer.tileTexture);
                }
                if (this.tilesCach[forwardIndex[3]] && this.tilesCach[forwardIndex[3]].tileTexture.hasLoad) {
                    const tileBuffer = this.tilesCach[forwardIndex[3]];
                    this.renderTile(tileBuffer.positionVertexBuffer, tileBuffer.texCoordVertexBuffer, tileBuffer.normalVertexBuffer, tileBuffer.indexBuffer, tileBuffer.n, tileBuffer.tileTexture);
                }
            }
        }
    }

    renderTile(positionVertexBuffer, texCoordVertexBuffer, normalVertexBuffer, indexBuffer, n, tileTexture) {
        const gl = this.gl;

        gl.enable(gl.BLEND);
        gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
        // gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
        // gl.disable(gl.DEPTH_TEST);
        // gl.depthMask(true);

        gl.enable(gl.CULL_FACE);

        gl.bindBuffer(gl.ARRAY_BUFFER, positionVertexBuffer);
        gl.vertexAttribPointer(this.attribLocation.a_Position, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(this.attribLocation.a_Position);

        gl.bindBuffer(gl.ARRAY_BUFFER, texCoordVertexBuffer);
        gl.vertexAttribPointer(this.attribLocation.a_TexCoord, 2, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(this.attribLocation.a_TexCoord);

        gl.bindBuffer(gl.ARRAY_BUFFER, normalVertexBuffer);
        gl.vertexAttribPointer(this.attribLocation.a_Normal, 3, gl.FLOAT, false, 0, 0);
        gl.enableVertexAttribArray(this.attribLocation.a_Normal);

        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);

        gl.activeTexture(gl.TEXTURE0);
        gl.bindTexture(gl.TEXTURE_2D, tileTexture);

        gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_SHORT, 0);

        gl.disable(gl.BLEND);
        gl.disable(gl.CULL_FACE);
    }
}

// 加载指定瓦块的顶点信息及纹理图片
function loadTexture(radius, globe, zoomInt, i, j, url, pole, lbLngLat, rtLngLat) {
    const s = 20037508.3427892;
    const devide = Math.pow(2, zoomInt);
    const unit = s * 2 / devide;

    const lbMercator = [-20037508.3427892 + i * unit, -20037508.3427892 + j * unit];
    const rtMercator = [-20037508.3427892 + (i + 1) * unit, -20037508.3427892 + (j + 1) * unit];
    if (!pole && !lbLngLat) lbLngLat = WebMercator2lonLat(-20037508.3427892 + i * unit, -20037508.3427892 + j * unit);
    if (!pole && !rtLngLat) rtLngLat = WebMercator2lonLat(-20037508.3427892 + (i + 1) * unit, -20037508.3427892 + (j + 1) * unit);
    
    const gl = globe.gl;

    const vertices = [];
    const normals = [];
    const texCoords = [];

    const lbLatUnit = modAfterCeil(lbLngLat[1], 6);
    const rtLatUnit = modAfterFloor(rtLngLat[1], 6);
    const lbLngUnit = modAfterCeil(lbLngLat[0], 12);
    const rtLngUnit = modAfterFloor(rtLngLat[0], 12);

    let latitudeBands = Math.floor((rtLatUnit - lbLatUnit) / 6);
    let longitudeBands = Math.floor((rtLngUnit - lbLngUnit) / 12);

    if (latitudeBands < 0) latitudeBands = -1;
    if (longitudeBands < 0) longitudeBands = -1;

    for (let latNumber = 0; latNumber <= latitudeBands + 2; latNumber++) {
        for (let longNumber = 0; longNumber <= longitudeBands + 2; longNumber++) {
            let lat = -1;
            let lng = -1;
            if (latNumber === 0) {
                lat = lbLngLat[1];
            } else if (latNumber === latitudeBands + 2) {
                lat = rtLngLat[1];
            } else {
                let mod = Math.ceil(lbLngLat[1]) % 6;
                if (lbLngLat[1] < 0) {
                    lat = Math.ceil(lbLngLat[1]) + Math.abs(mod) + (latNumber - 1) * 6;
                } else {
                    lat = Math.ceil(lbLngLat[1]) + (6 - Math.abs(mod)) + (latNumber - 1) * 6;
                }
            }
            if (longNumber === 0) {
                lng = lbLngLat[0];
            } else if (longNumber === longitudeBands + 2) {
                lng = rtLngLat[0];
            } else {
                let mod = Math.ceil(lbLngLat[0]) % 12;
                if (lbLngLat[0] < 0) {
                    lng = Math.ceil(lbLngLat[0]) + Math.abs(mod) + (longNumber - 1) * 12;
                } else {
                    lng = Math.ceil(lbLngLat[0]) + (12 - Math.abs(mod)) + (longNumber - 1) * 12;
                }
            }

            const thetaPhiXYZ = lngLat2ThetaPhiXYZ([lng, lat]);
            const mecator = lonLat2WebMercator(lng, lat);

            let x = thetaPhiXYZ.x;
            let y = thetaPhiXYZ.y;
            let z = thetaPhiXYZ.z;
            let s = (mecator[0] - lbMercator[0]) / unit;
            let t = (rtMercator[1] - mecator[1]) / unit;

            normals.push(x);
            normals.push(y);
            normals.push(z);
            texCoords.push(s);
            if (pole === 'n') {
                texCoords.push(0);
            }
            else if (pole === 's') {
                texCoords.push(1);
            }
            else {
                texCoords.push(t);
            }
            vertices.push(radius * x);
            vertices.push(radius * y);
            vertices.push(radius * z);
        }
    }

    const indices = [];
    for (let latNumber = 0; latNumber < latitudeBands + 2; latNumber++) {
        for (let longNumber = 0; longNumber < longitudeBands + 2; longNumber++) {
            let first = (latNumber * (longitudeBands + 3)) + longNumber;
            let second = first + longitudeBands + 3;
            indices.push(first);
            indices.push(second);
            indices.push(first + 1);

            indices.push(second);
            indices.push(second + 1);
            indices.push(first + 1);
        }
    }

    const positionVertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, positionVertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

    const texCoordVertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordVertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(texCoords), gl.STATIC_DRAW);

    const normalVertexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, normalVertexBuffer);
    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(normals), gl.STATIC_DRAW);

    const indexBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
    gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);

    const imageTile = new Image();
    if (!imageTile) {
        console.log('Failed to create the image object');
        return false;
    }
    const tileTexture = gl.createTexture();
    tileTexture.hasLoad = false;
    imageTile.onload = () => {
        gl.bindTexture(gl.TEXTURE_2D, tileTexture);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, imageTile);
        tileTexture.hasLoad = true;
        // globe.updateSence();
    };
    imageTile.crossOrigin = 'anonymous';

    if (url === 'tecent') {
        imageTile.src = 'http://p1.map.gtimg.com/sateTiles/' + zoomInt + '/' + Math.floor(i / 16) + '/' + Math.floor(j / 16) + '/' + i + '_' + j + '.jpg?version=228';
    }
    else {
        let imageUrl = url.replace(/{x}/g, i);
        imageUrl = imageUrl.replace(/{y}/g, j);
        imageUrl = imageUrl.replace(/{z}/g, zoomInt);
        imageUrl = imageUrl.replace(/{reverseY}/g, (devide - 1 - j));
        imageUrl = imageUrl.replace(/{reverseX}/g, (devide - 1 - i));
        imageTile.src = imageUrl;
    }
    // imageTile.src = '//api.mapbox.com/v4/mapbox.streets-satellite/' + zoomInt + '/' + i + '/' + (devide -1 - j) + '.png?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NDg1bDA1cjYzM280NHJ5NzlvNDMifQ.d6e-nNyBDtmQCVwVNivz7A';
    // imageTile.src = '//a.tile.openstreetmap.org/' + zoomInt + '/' + i + '/' + (devide - 1 - j) + '.png';
    // imageTile.src = '//mt1.google.cn/vt/lyrs=s,r&hl=zh-CN&gl=cn&x=' + i + '&y=' + (devide - 1 - j) + '&z=' + zoomInt;

    
    return {
        zoomInt: zoomInt,
        x: i,
        y: j,
        positionVertexBuffer: positionVertexBuffer,
        texCoordVertexBuffer: texCoordVertexBuffer,
        normalVertexBuffer: normalVertexBuffer,
        indexBuffer: indexBuffer,
        n: indices.length,
        tileTexture: tileTexture
    }
}

// 经纬度转墨卡托
function lonLat2WebMercator(lng, lat) {
    const x = lng * 20037508.3427892 / 180;
    let y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / (Math.PI / 180);
    y = y * 20037508.3427892 / 180;
    return [x, y];
}

// 墨卡托转经纬度
function WebMercator2lonLat(x, y) {
    const lng = x / 20037508.3427892 * 180;
    let lat = y / 20037508.3427892 * 180;
    lat = 180 / Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI / 180)) - Math.PI / 2);
    return [lng, lat];
}

// 经纬度转webgl空间坐标
function lngLat2ThetaPhiXYZ(lngLat) {
    const theta = 90 - lngLat[1];
    const phi = 180 - lngLat[0];
    const sinTheta = Math.sin(theta / 180 * Math.PI);
    const cosTheta = Math.cos(theta / 180 * Math.PI);
    const sinPhi = Math.sin(phi / 180 * Math.PI);
    const cosPhi = Math.cos(phi / 180 * Math.PI);
    const x = cosPhi * sinTheta;
    const y = cosTheta;
    const z = sinPhi * sinTheta;

    return {
        theta: theta,
        phi: phi,
        x: x,
        y: y,
        z: z
    };
}

function modAfterCeil(number, modNumber) {
    let mod = Math.ceil(number) % modNumber;
    if (number < 0) {
        return Math.ceil(number) + Math.abs(mod);
    } else {
        return Math.ceil(number) + (modNumber - Math.abs(mod));
    }
}

function modAfterFloor(number, modNumber) {
    let mod = Math.floor(number) % modNumber;
    if (number < 0) {
        return Math.floor(number) - (modNumber - Math.abs(mod));
    } else {
        return Math.floor(number) - mod;
    }
}

// 获取指定zoom级别的全部瓦块信息
function getTilesCorners(n) {
    const tilesCorners = {};
    const s = 20037508.3427892;
    const devide = Math.pow(2, n);
    const unit = s * 2 / devide;
    for (let i = 0; i < devide; i++) {
        for (let j = 0; j < devide; j++) {
            tilesCorners[n + '+' + i + '+' + j] = {
                i: i,
                j: j,
                lbMercator: [-20037508.3427892 + i * unit, -20037508.3427892 + j * unit],
                rtMercator: [-20037508.3427892 + (i + 1) * unit, -20037508.3427892 + (j + 1) * unit],
                lbLngLat: WebMercator2lonLat(-20037508.3427892 + i * unit, -20037508.3427892 + j * unit),
                rtLngLat: WebMercator2lonLat(-20037508.3427892 + (i + 1) * unit, -20037508.3427892 + (j + 1) * unit),
            }
        }
    }
    return tilesCorners;
}

// 获取两极指定zoom级别的瓦块
function getPoleTilesCorners(n) {
    const poleTilesCorners = {};
    const s = 20037508.3427892;
    const devide = Math.pow(2, n);
    const unit = s * 2 / devide;
    for (let i = 0; i < devide; i++) {
        poleTilesCorners['n' + i] = {
            pole: 'n',
            i: i,
            j: (devide - 1),
            lbLngLat: WebMercator2lonLat(-20037508.3427892 + i * unit, -20037508.3427892 + devide * unit),
            rtLngLat: [WebMercator2lonLat(-20037508.3427892 + (i + 1) * unit, -20037508.3427892 + devide * unit)[0], 90],
        }
    }
    for (let i = 0; i < devide; i++) {
        poleTilesCorners['s' + i] = {
            pole: 's',
            i: i,
            j: 0,
            lbLngLat: [WebMercator2lonLat(-20037508.3427892 + i * unit, -20037508.3427892 + 0 * unit)[0], -90],
            rtLngLat: WebMercator2lonLat(-20037508.3427892 + (i + 1) * unit, -20037508.3427892 + 0 * unit),
        }
    }
    return poleTilesCorners;
}
